package cn.tedu.travelsystem.itinerary.service.impl;


import cn.tedu.travelsystem.hotel.mapper.HotelMapper;
import cn.tedu.travelsystem.hotel.pojo.entity.Hotel;
import cn.tedu.travelsystem.itinerary.mapper.ItineraryMapper;
import cn.tedu.travelsystem.itinerary.pojo.dto.ItineraryRequestDTO;
import cn.tedu.travelsystem.itinerary.pojo.entity.Itinerary;
import cn.tedu.travelsystem.itinerary.pojo.vo.DailyPlanVO;
import cn.tedu.travelsystem.itinerary.pojo.vo.ItineraryVO;
import cn.tedu.travelsystem.itinerary.pojo.vo.SpotVO;
import cn.tedu.travelsystem.itinerary.service.ItineraryService;
import cn.tedu.travelsystem.itineraryDetail.mapper.ItineraryDetailMapper;
import cn.tedu.travelsystem.itineraryDetail.pojo.entity.ItineraryDetail;
import cn.tedu.travelsystem.scenicSpot.mapper.ScenicSpotMapper;
import cn.tedu.travelsystem.scenicSpot.pojo.entity.ScenicSpot;
import cn.tedu.travelsystem.transport.mapper.TransportMapper;
import cn.tedu.travelsystem.transport.pojo.entity.Transport;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;


@Service
@Slf4j
public class ItineraryServiceImpl implements ItineraryService {
    @Autowired
    private ItineraryDetailMapper itineraryDetailMapper;

    @Autowired
    private ScenicSpotMapper spotMapper;
    @Autowired private HotelMapper hotelMapper;
    @Autowired private TransportMapper transportMapper;
    @Autowired private ItineraryMapper itineraryMapper;

    public ItineraryVO generateItinerary(ItineraryRequestDTO request) {
        if (request.getDurationDays() <= 0) {
            throw new IllegalArgumentException("无效的行程天数: " + request.getDurationDays());
        }
        // 1. 获取推荐资源
        List<ScenicSpot> spots = spotMapper.selectByTagsAndBudget(
                request.getInterestTags(),
                parseBudget(request.getBudgetRange())
        );

        List<Hotel> hotels = hotelMapper.selectByBudget(
                parseBudget(request.getBudgetRange())
        );

        if (hotels.isEmpty()) {
            throw new IllegalStateException("没有符合预算的酒店");
        }

        List<Transport> transports = transportMapper.selectByBudget(
                parseBudget(request.getBudgetRange())
        );

        if (transports.isEmpty()) {
            throw new IllegalStateException("没有符合预算的交通工具");
        }

        // 2. 生成每日行程安排
        List<DailyPlan> dailyPlans = new ArrayList<>();
        int days = request.getDurationDays();
        if (days <= 0) {
            throw new IllegalArgumentException("行程天数必须大于0");
        }
        int spotsPerDay = (int) Math.ceil((double) spots.size() / days);

        for (int day = 1; day <= days; day++) {
            DailyPlan plan = new DailyPlan();
            plan.setDayNumber(day);

            // 分配景点
            List<ScenicSpot> dailySpots = spots.stream()
                    .skip((day-1)*spotsPerDay)
                    .limit(spotsPerDay)
                    .collect(Collectors.toList());
            plan.setSpots(dailySpots);

            // 分配酒店
            plan.setHotel(hotels.get(day % hotels.size()));

            // 分配交通
            plan.setTransport(transports.get(day % transports.size()));

            dailyPlans.add(plan);
        }

        // 3. 计算总预算
        BigDecimal totalBudget = calculateTotalBudget(dailyPlans);

        // 4. 保存行程
        Itinerary itinerary = new Itinerary();
        itinerary.setUser_id(request.getUserId());
        itinerary.setStart_date(new Date());
        itinerary.setTotal_budget(totalBudget.doubleValue());
        itinerary.setGenerated_by("AI生成");
        itinerary.setItinerary_status("进行中");
        itineraryMapper.insert(itinerary);

        // 5. 保存行程详情
        try {
            saveItineraryDetails(itinerary.getItinerary_id(), dailyPlans);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }

        return convertToVO(itinerary, dailyPlans);
    }

    private void saveItineraryDetails(Integer itineraryId, List<DailyPlan> plans) throws ParseException {
        for (DailyPlan plan : plans) {
            ItineraryDetail detail = new ItineraryDetail();
//            detail.setItinerary_id(itineraryId);
            detail.setDay_number(plan.getDayNumber());
            // 安全获取景点 ID
//            if (plan.getSpots() != null && !plan.getSpots().isEmpty()) {
//                detail.setSpot_id(plan.getSpots().get(0).getSpot_id());
//            } else {
//                detail.setSpot_id(null); // 或者设置默认值、抛出业务异常
//            }
//
//            // 安全获取酒店 ID
//            if (plan.getHotel() != null) {
//                detail.setHotel_id(plan.getHotel().getHotel_id());
//            } else {
//                detail.setHotel_id(null);
//            }
//
//            // 安全获取交通 ID
//            if (plan.getTransport() != null) {
//                detail.setTransport_id(plan.getTransport().getTransport_id());
//            } else {
//                detail.setTransport_id(null);
//            }
            // 设置时间（示例逻辑）
            SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
            detail.setStart_time(sdf.parse("09:00"));
            detail.setEnd_time(sdf.parse("18:00"));
            itineraryDetailMapper.insert(detail);
        }

    }
    private BigDecimal parseBudget(String budgetRange) {
        // 处理类似 "1000-2000" 的输入
        String[] parts = budgetRange.split("-");
        return new BigDecimal(parts[1]); // 返回最大值
    }

    private BigDecimal calculateTotalBudget(List<DailyPlan> dailyPlans) {
        BigDecimal total = BigDecimal.ZERO;
        for (DailyPlan plan : dailyPlans) {
            // 计算单日费用
            BigDecimal dayCost = calculateDailyCost(plan);
            total = total.add(dayCost);
        }
        return total.setScale(2, RoundingMode.HALF_UP); // 保留两位小数
    }

    // 辅助方法：计算单日费用
    private BigDecimal calculateDailyCost(DailyPlan plan) {
        // 景点总费用
        BigDecimal spotsCost = plan.getSpots().stream()
                .map(ScenicSpot::getNormal_price)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 酒店费用
        BigDecimal hotelCost = Optional.ofNullable(plan.getHotel())
                .map(Hotel::getNormal_price)
                .orElse(BigDecimal.ZERO);

        // 交通费用
        BigDecimal transportCost =  Optional.ofNullable(plan.getTransport())
                .map(Transport::getPrice)
                .orElse(BigDecimal.ZERO);

        return spotsCost.add(hotelCost).add(transportCost);
    }

    // 在 ItineraryServiceImpl 中添加以下代码
    private ItineraryVO convertToVO(Itinerary itinerary, List<DailyPlan> dailyPlans) {
        ItineraryVO vo = new ItineraryVO();

        // 基础字段拷贝
        BeanUtils.copyProperties(itinerary, vo);

        // 字段格式化
        vo.setFormattedStartDate(formatDate(itinerary.getStart_date()));
        vo.setTotalBudget(formatCurrency(itinerary.getTotal_budget()));
        vo.setStatusDisplay(getStatusDisplayName(itinerary.getItinerary_status()));

        // 转换每日计划
        List<DailyPlanVO> dailyPlanVOs = dailyPlans.stream()
                .map(this::convertDailyPlanToVO)
                .collect(Collectors.toList());
        vo.setDailyPlans(dailyPlanVOs);

        return vo;
    }

    // 辅助方法：转换每日计划
    private DailyPlanVO convertDailyPlanToVO(DailyPlan plan) {
        DailyPlanVO vo = new DailyPlanVO();
        vo.setDayNumber(plan.getDayNumber());

        // 景点信息转换
        List<SpotVO> spotVOs = plan.getSpots().stream()
                .map(spot -> {
                    SpotVO spotVO = new SpotVO();
                    ScenicSpot scenicSpot = spotMapper.selectById(spot.getSpot_id());
                    spotVO.setName(scenicSpot.getSpot_name());
                    spotVO.setPrice(spot.getNormal_price().doubleValue());
                    return spotVO;
                })
                .collect(Collectors.toList());
        vo.setSpots(spotVOs);

        // 酒店信息
        vo.setHotelName(hotelMapper.selectById(plan.getHotel().getHotel_id()));

        // 交通信息
        Transport transport = null;
        if (plan.getTransport() != null && plan.getTransport().getTransport_id() != null) {
            transport = transportMapper.selectById(plan.getTransport().getTransport_id());
        }
        if (transport != null) {
            vo.setTransportInfo(String.format("%s %s-%s",
                    transport.getType(),
                    transport.getDeparture(),
                    transport.getDestination()));
        } else {
            vo.setTransportInfo("未知交通");
        }

        // 时间格式化
        vo.setTimeRange(formatTimeRange(plan.getStartTime(), plan.getEndTime()));

        return vo;
    }

    // 其他工具方法
    private String formatDate(Date date) {
        return DateTimeFormatter.ofPattern("yyyy-MM-dd")
                .format(date.toInstant().atZone(ZoneId.systemDefault()));
    }

    private String formatCurrency(Double amount) {
        return NumberFormat.getCurrencyInstance(Locale.CHINA)
                .format(amount);
    }

    private String getStatusDisplayName(String status) {
        Map<String, String> statusMap = new HashMap<>();
        statusMap.put("进行中", "In Progress");
        statusMap.put("已完成", "Completed");
        return statusMap.getOrDefault(status, "Unknown");
    }

    private String formatTimeRange(LocalTime start, LocalTime end) {
        if (start == null || end == null) {
            return "";
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm");
        return String.format("%s - %s", start.format(formatter), end.format(formatter));
    }

@Data
    public static class DailyPlan {
        private Integer dayNumber;         // 第几天（例如：1,2,3...）
        private List<ScenicSpot> spots;    // 当日景点列表（故宫、颐和园）
        private Hotel hotel;               // 当日酒店（如家酒店）
        private Transport transport;       // 当日交通工具（高铁G101）
        private LocalTime startTime;       // 当日开始时间
        private LocalTime endTime;         // 当日结束时间
        private BigDecimal dayBudget;      // 当日预算
    }
}
